﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Windows;
using System.Reflection;
using log4net;
using System.Windows.Threading;
using System.Threading;
using System.Globalization;
using Avalon.Windows.Controls;
using System.Windows.Controls;
using OpenExpressApp.MetaModel.Audit;
using System.Windows.Markup;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using OpenExpressApp.Library;
using System.IO;

namespace OpenExpressApp
{
    /// <summary>
    /// 唯一的应用程序实例。
    /// 
    /// 使用Bootstrapper进行初始化
    /// 进行错误处理。
    /// </summary>
    public partial class App : Application
    {
        public App()
        {
            Thread.CurrentThread.CurrentUICulture = new CultureInfo("zh-CHS");
            FrameworkElement.LanguageProperty.OverrideMetadata(typeof(FrameworkElement),
                new FrameworkPropertyMetadata(XmlLanguage.GetLanguage("zh-CN")));

            this.DispatcherUnhandledException += OnDispatcherUnhandledException;

            //是否能登录成功
            if (LoginWindow.Execute())
            {
                if (Compose())
                {
                    //Application.Current.Run(_container.GetExportedValue<Window>("OpenExpressApp.MainWindow")); 
                    _container.GetExportedValue<Window>("OpenExpressApp.MainWindow").Show();
                }
            }
            else
            {
                this.Shutdown();
            }
        }

        private CompositionContainer _container;


        protected override void OnExit(ExitEventArgs e)
        {
            base.OnExit(e);
            if (_container != null)
            {
                _container.Dispose();
            }
        }

        private bool Compose()
        {
            var catalog = new AggregateCatalog();
            catalog.Catalogs.Add(new AssemblyCatalog(Assembly.GetExecutingAssembly()));
            catalog.Catalogs.Add(new AssemblyCatalog(Assembly.GetAssembly(typeof(OpenExpressApp.Module.ExpressAppModule))));
            catalog.Catalogs.Add(new AssemblyCatalog(Assembly.GetAssembly(typeof(OpenExpressApp.Module.WPF.SystemModule.WPFModule))));
            if (Directory.Exists(@".\Module")) catalog.Catalogs.Add(new DirectoryCatalog(@".\Module"));

            _container = new CompositionContainer(catalog);
            _container.ComposeExportedValue<CompositionContainer>(_container);

            var modules = _container.GetExportedValues<IModule>();
            foreach (var module in modules)
            {
                module.Initialize();
            }

            CompositionBatch batch = new CompositionBatch();
            batch.AddPart(this);
            _container.Compose(batch);

            return true;
        }

        #region 处理异常
        /// <summary>
        /// 应用程序异常处理。
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OnDispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
        {
            try
            {
                Exception ex = LastInnerException(e.Exception);
                TaskDialog taskDialog = new TaskDialog
                {
                    Width = 600,
                    Title = "错误",
                    Content = ex.Message,
                    ExpansionPosition = TaskDialogExpansionPosition.Footer,
                    ExpansionButtonContent = "详细信息",
                    ExpansionContent = new TextBox()
                    {
                        AcceptsReturn = true,
                        Text = e.Exception.ToString(),
                        Height = 300
                    }
                };

                taskDialog.Show();

                ILog log = log4net.LogManager.GetLogger("OpenExpressApp");
                log.Error("系统未捕获异常", e.Exception);

                e.Handled = true;
            }
            catch { }
        }

        private Exception LastInnerException(Exception ex)
        {
            Exception result = ex;
            while (null != result)
            {
                if (null == result.InnerException)
                {
                    return result;
                }
                result = result.InnerException;
            }
            return ex;
        }

        private GException FirstGException(Exception ex)
        {
            Exception result = ex;
            while ((null != result) && (!(result is GException)))
            {
                result = result.InnerException;
            }
            if (result is GException)
            {
                return result as GException;
            }
            else
            {
                return null;
            }
        }

        #endregion
    }
}